package co.gov.medellin.ssti.sub.model.dao.impl;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcDaoSupport;

import co.gov.medellin.ssti.sub.model.dao.RepBeneficioOtorgadoDAO;
import co.gov.medellin.ssti.sub.model.vo.ProgramaVO;
import co.gov.medellin.ssti.sub.model.vo.RepAtributoVO;
import co.gov.medellin.ssti.sub.model.vo.RepBeneficioOtorgadoVO;
import co.gov.medellin.ssti.sub.model.vo.SubprogramaVO;
import co.gov.medellin.ssti.sub.model.vo.VflexVO;

public class RepBeneficioOtorgadoDAOImpl2 extends NamedParameterJdbcDaoSupport
		implements RepBeneficioOtorgadoDAO {

	public Collection<RepBeneficioOtorgadoVO> findBeneficioOtorgadoByCriteria(
			RepBeneficioOtorgadoVO criteria) {
		Map<String, Object> namedParameters = new HashMap<String, Object>();

		StringBuffer query = new StringBuffer(
				"SELECT COUNT(beneotor.codigo) cantidad_otorgada, sede.CODIGO codsede, "
						+ " sede.NOMBRE nomsede, prog.CODIGO codpro, prog.NOMBRE nompro, "
						+ " subpro.CODIGO codsubpro, subpro.NOMBRE nomsubpro "
						+ " FROM TCS_BEN_PROGRAMA prog, TCS_BEN_SUBPROGRAMA subpro, "
						+ " TCS_BEN_BENEFICIO_OTORGADO beneotor, TCS_BEN_SEDE sede "
						+ " WHERE beneotor.SBPR_CODIGO =  subpro.CODIGO "
						+ " AND beneotor.SEDE_CODIGO = sede.CODIGO AND subpro.PRG_CODIGO = prog.CODIGO "
						+ " AND beneotor.FECHA_BENEFICIO <= sysdate AND prog.vigencia='A' AND subpro.vigencia='A' ");

		if ((Object) criteria.getCodeSede() != null) {
			query.append(" AND sede.CODIGO = :sede.CODIGO ");
			namedParameters.put("sede.CODIGO", criteria.getCodeSede());
		}
		if ((Object) criteria.getCodeSubprograma() != null) {
			query.append(" AND subpro.CODIGO = :subpro.CODIGO ");
			namedParameters.put("subpro.CODIGO", criteria.getCodeSubprograma());
		}
		if ((Object) criteria.getCodePrograma() != null) {
			query.append(" AND prog.CODIGO = :prog.CODIGO ");
			namedParameters.put("prog.CODIGO", criteria.getCodePrograma());
		}

		if ((Object) criteria.getDesde() != null
				&& (Object) criteria.getHasta() != null) {
			query.append(" AND beneotor.FECHA_BENEFICIO BETWEEN TO_DATE(:DESDE,'dd/mm/yyyy') AND TO_DATE(:HASTA,'dd/mm/yyyy')");
			namedParameters.put("DESDE", criteria.getDesde());
			namedParameters.put("HASTA", criteria.getHasta());
		}

		if ((Object) criteria.getGestor() != null
				&& criteria.getCodigoAtrGestor() != null) {
			query.append(" AND Fcs_Ben_Valor_Atributo(:codigoAtrGestor, beneotor.CODIGO, beneotor.BEN_CODIGO, beneotor.FECHA_BENEFICIO) = :gestor ");
			namedParameters.put("codigoAtrGestor",
					criteria.getCodigoAtrGestor());
			namedParameters.put("gestor", criteria.getGestor());
		}
		query.append(" GROUP BY sede.CODIGO, sede.NOMBRE, prog.CODIGO, prog.NOMBRE, subpro.CODIGO, "
				+ "subpro.NOMBRE");

		query.append(" ORDER BY prog.NOMBRE,subpro.NOMBRE,sede.NOMBRE ");

		final String desde = criteria.getDesde();
		final String hasta = criteria.getHasta();

		List<RepBeneficioOtorgadoVO> lbeneotor = getNamedParameterJdbcTemplate()
				.query(query.toString(), namedParameters,
						new RowMapper<RepBeneficioOtorgadoVO>() {

							public RepBeneficioOtorgadoVO mapRow(ResultSet rst,
									int rowNum) throws SQLException {
								RepBeneficioOtorgadoVO vo = new RepBeneficioOtorgadoVO();
								vo.setCodeSede(new Long(rst.getLong("codsede")));
								vo.setNombreSede(rst.getString("nomsede"));
								vo.setCodePrograma(new Long(rst
										.getLong("codpro")));
								vo.setNombrePrograma(rst.getString("nompro"));
								vo.setCodeSubprograma(new Long(rst
										.getLong("codsubpro")));
								vo.setNombreSubprograma(rst
										.getString("nomsubpro"));
								vo.setDesde(desde);
								vo.setHasta(hasta);
								vo.setCantidad(rst
										.getString("cantidad_otorgada"));
								return vo;
							}
						});
		return lbeneotor;
	}

	public Collection<RepBeneficioOtorgadoVO> findBeneficioOtorgadoConGestorByCriteria(
			RepBeneficioOtorgadoVO criteria) {
		Map<String, Object> namedParameters = new HashMap<String, Object>();

		StringBuffer query = new StringBuffer(
				"SELECT COUNT(beneotor.codigo) cantidad_otorgada, sede.CODIGO codsede, "
						+ " sede.NOMBRE nomsede, prog.CODIGO codpro, prog.NOMBRE nompro, "
						+ " subpro.CODIGO codsubpro, subpro.NOMBRE nomsubpro "
						+ " FROM TCS_BEN_PROGRAMA prog, TCS_BEN_SUBPROGRAMA subpro, "
						+ " TCS_BEN_BENEFICIO_OTORGADO beneotor, TCS_BEN_SEDE sede, TCS_BEN_SUBP_ATR_BENEFICIARIO sab "
						+ " WHERE beneotor.SBPR_CODIGO =  subpro.CODIGO "
						+ " AND beneotor.SEDE_CODIGO = sede.CODIGO AND subpro.PRG_CODIGO = prog.CODIGO "
						+ " AND beneotor.FECHA_BENEFICIO <= sysdate AND prog.vigencia='A' AND subpro.vigencia='A' "
						+ " AND sab.sbpr_codigo = subpro.codigo AND UPPER(TRIM(sab.NOMBRE)) = 'GESTOR' ");

		if ((Object) criteria.getCodeSede() != null) {
			query.append(" AND sede.CODIGO = :sede.CODIGO ");
			namedParameters.put("sede.CODIGO", criteria.getCodeSede());
		}
		if ((Object) criteria.getCodeSubprograma() != null) {
			query.append(" AND subpro.CODIGO = :subpro.CODIGO ");
			namedParameters.put("subpro.CODIGO", criteria.getCodeSubprograma());
		}
		if ((Object) criteria.getCodePrograma() != null) {
			query.append(" AND prog.CODIGO = :prog.CODIGO ");
			namedParameters.put("prog.CODIGO", criteria.getCodePrograma());
		}
		if ((Object) criteria.getDesde() != null
				&& (Object) criteria.getHasta() != null) {
			query.append(" AND beneotor.FECHA_BENEFICIO BETWEEN TO_DATE(:DESDE,'dd/mm/yyyy') AND TO_DATE(:HASTA,'dd/mm/yyyy')");
			namedParameters.put("DESDE", criteria.getDesde());
			namedParameters.put("HASTA", criteria.getHasta());
		}
		if ((Object) criteria.getGestor() != null
				&& criteria.getCodigoAtrGestor() != null) {
			query.append(" AND Fcs_Ben_Valor_Atributo(:codigoAtrGestor, beneotor.CODIGO, beneotor.BEN_CODIGO, beneotor.FECHA_BENEFICIO) = :gestor ");
			namedParameters.put("codigoAtrGestor",
					criteria.getCodigoAtrGestor());
			namedParameters.put("gestor", criteria.getGestor());
		}
		query.append(" GROUP BY sede.CODIGO, sede.NOMBRE, prog.CODIGO, prog.NOMBRE, subpro.CODIGO, "
				+ "subpro.NOMBRE");
		query.append(" ORDER BY prog.NOMBRE,subpro.NOMBRE,sede.NOMBRE ");

		final String desde = criteria.getDesde();
		final String hasta = criteria.getHasta();

		List<RepBeneficioOtorgadoVO> lbeneotor = getNamedParameterJdbcTemplate()
				.query(query.toString(), namedParameters,
						new RowMapper<RepBeneficioOtorgadoVO>() {

							public RepBeneficioOtorgadoVO mapRow(ResultSet rst,
									int rowNum) throws SQLException {
								RepBeneficioOtorgadoVO vo = new RepBeneficioOtorgadoVO();
								vo.setCodeSede(new Long(rst.getLong("codsede")));
								vo.setNombreSede(rst.getString("nomsede"));
								vo.setCodePrograma(new Long(rst
										.getLong("codpro")));
								vo.setNombrePrograma(rst.getString("nompro"));
								vo.setCodeSubprograma(new Long(rst
										.getLong("codsubpro")));
								vo.setNombreSubprograma(rst
										.getString("nomsubpro"));
								vo.setDesde(desde);
								vo.setHasta(hasta);
								vo.setCantidad(rst
										.getString("cantidad_otorgada"));
								return vo;
							}

						});

		return lbeneotor;
	}

	public Collection<VflexVO> findListaAtri(Long codeAtri) {
		Map<String, Object> namedParameters = new HashMap<String, Object>();

		String query = "SELECT vfl.DESCRIPCION descrip, vfl.CODIGO_VALOR codvalor "
				+ " FROM TCS_BEN_SUBP_ATR_BENEFICIARIO atri, "
				+ " paoyer.TCS_TIPO_VALOR_FLEX tvfl, paoyer.TCS_VALOR_FLEXIBLE vfl "
				+ " WHERE atri.CODIGO = :CODIGO "
				+ " AND atri.TTVF_CODIGO_DOMINIO = tvfl.CODIGO "
				+ " AND tvfl.CODIGO = vfl.TVF_CODIGO AND vfl.VIGENCIA='S'";

		namedParameters.put("CODIGO", codeAtri);

		List<VflexVO> lista = getNamedParameterJdbcTemplate().query(query,
				namedParameters, new RowMapper<VflexVO>() {

					public VflexVO mapRow(ResultSet rst, int rowNum)
							throws SQLException {
						VflexVO vo = new VflexVO();
						vo.setDescVflex(rst.getString("descrip"));
						vo.setCodigoVflex(rst.getString("codvalor"));
						vo.setNombreVflex(rst.getString("codvalor") + "~"
								+ rst.getString("descrip"));
						return vo;
					}
				});
		return lista;
	}

	public Collection<RepAtributoVO> findAtributoEspecificos(
			Long codeSubprograma) {
		Map<String, Object> namedParameters = new HashMap<String, Object>();

		String query = "SELECT CODIGO, TIPO_ATRIBUTO, NOMBRE, nvl(REST_CODIGO,'0') REST_CODIGO, ORDEN, LONGITUD, "
				+ " OBLIGATORIO, ETIQUETA, VALOR_SUGERIDO, VALIDAR_LISTA, VIGENCIA, "
				+ " DESCRIPCION, TIPO_DATO, TTVF_CODIGO_DOMINIO "
				+ " FROM TCS_BEN_SUBP_ATR_BENEFICIARIO WHERE SBPR_CODIGO = :SBPR_CODIGO "
				+ " AND VIGENCIA = 'A' ORDER BY ORDEN";

		namedParameters.put("SBPR_CODIGO", codeSubprograma);

		List<RepAtributoVO> listaAtriEsp = getNamedParameterJdbcTemplate()
				.query(query, namedParameters, new RowMapper<RepAtributoVO>() {

					public RepAtributoVO mapRow(ResultSet rst, int rowNum)
							throws SQLException {
						RepAtributoVO vo = new RepAtributoVO();
						vo.setCodigo(new Long(rst.getString("CODIGO")));
						vo.setEtiqueta(rst.getString("ETIQUETA"));
						vo.setOrigen("E");
						return vo;
					}
				});
		return listaAtriEsp;
	}

	public Collection<ProgramaVO> findProgramaByUserReport(Long codeUser,
			String userGroupName, Long codeArea) {
		Map<String, Object> namedParameters = new HashMap<String, Object>();

		ProgramaVO criteria = new ProgramaVO();

		StringBuffer query = new StringBuffer(
				"SELECT DISTINCT pro.CODIGO COD_PROGRAMA, pro.NOMBRE NOM_PROGRAMA, pro.DESCRIPCION DESC_PROGRAMA, "
						+ " pro.OBJETIVO, pro.POBLACION_OBJETIVO, area.CODIGO COD_AREA, area.NOMBRE NOM_AREA, "
						+ " usu.CODIGO COD_USUARIO, usu.NOMBRE NOM_USUARIO, a.admProg "
						+ " FROM VCS_BEN_SUBPROG_ALLOWED a, "
						+ " TCS_BEN_PROGRAMA pro, TCS_BEN_AREA area, paoyer.TCS_USUARIO usu, "
						+ " paoyer.tcs_grupo_usuario gus, TCS_BEN_SUBPROGRAMA_USUARIO subus "
						+ " WHERE  gus.CODIGO = usu.GUS_CODIGO "
						+ " AND a.COD_PROGRAMA = pro.CODIGO "
						+ " AND pro.AREA_CODIGO = area.CODIGO "
						+ " AND pro.USU_CODIGO = usu.CODIGO "
						+ " AND pro.VIGENCIA = 'A' ");

		if ((Object) codeUser != null) {
			query.append("AND ('ADMINISTRADOR GENERAL' = :userGroupName OR 'SUPER USUARIO' = :userGroupName "
					+ " OR admSubpro = :codeUser OR pro.USU_CODIGO = :codeUser "
					+ " OR a.permisos = :codeUser ");

			namedParameters.put("userGroupName", userGroupName);
			namedParameters.put("codeUser", codeUser);

			if (userGroupName != null
					&& userGroupName.equals("ADMINISTRADOR SECRETARIA")) {
				query.append(" OR COD_AREA = :COD_AREA ");
				namedParameters.put("COD_AREA", codeArea);
			}
			query.append(" ) ");
		} else {
			return null;
		}

		if (criteria.getCode() != null) {
			query.append(" AND COD_PROGRAMA = :COD_PROGRAMA ");
			namedParameters.put("COD_PROGRAMA", criteria.getCode());
		}
		if (!criteria.getNombre().equalsIgnoreCase("")) {
			query.append(" AND NOM_PROGRAMA LIKE :NOM_PROGRAMA ");
			namedParameters.put("NOM_PROGRAMA", "%"
					+ criteria.getNombre().toUpperCase().trim() + "%");
		}
		if (criteria.getCodeArea() != null) {
			query.append(" AND COD_AREA = :COD_AREA ");
			namedParameters.put("COD_AREA", criteria.getCodeArea());
		}
		query.append(" ORDER BY NOM_PROGRAMA");

		List<ProgramaVO> programas = getNamedParameterJdbcTemplate().query(
				query.toString(), namedParameters, new RowMapper<ProgramaVO>() {

					public ProgramaVO mapRow(ResultSet rst, int rowNum)
							throws SQLException {
						ProgramaVO pro = new ProgramaVO();
						pro.setCode(new Long(rst.getLong("COD_PROGRAMA")));
						pro.setNombre(rst.getString("NOM_PROGRAMA"));
						pro.setDescripcion(rst.getString("DESC_PROGRAMA"));
						pro.setObjetivo(rst.getString("OBJETIVO"));
						pro.setPoblacionObjetivo(rst
								.getString("POBLACION_OBJETIVO"));
						pro.setCodeArea(new Long(rst.getString("COD_AREA")));
						pro.setNombreArea(rst.getString("NOM_AREA"));
						pro.setCodeUsuario(new Long(rst
								.getString("COD_USUARIO")));
						pro.setNombreUsuario(rst.getString("NOM_USUARIO"));
						return pro;
					}
				});
		return programas;
	}

	public Collection<ProgramaVO> findProgramaWithGestorByUserReport(
			Long codeUser, String userGroupName, Long codeArea) {
		Map<String, Object> namedParameters = new HashMap<String, Object>();

		ProgramaVO criterea = new ProgramaVO();

		StringBuffer query = new StringBuffer(
				"SELECT DISTINCT pro.CODIGO COD_PROGRAMA, pro.NOMBRE NOM_PROGRAMA, pro.DESCRIPCION DESC_PROGRAMA, "
						+ "pro.OBJETIVO, pro.POBLACION_OBJETIVO, area.CODIGO COD_AREA, area.NOMBRE NOM_AREA, "
						+ "usu.CODIGO COD_USUARIO, usu.NOMBRE NOM_USUARIO, a.admProg "
						+ "FROM VCS_BEN_SUBPROG_ALLOWED a, "
						+ "TCS_BEN_PROGRAMA pro, TCS_BEN_AREA area, paoyer.TCS_USUARIO usu, TCS_BEN_SUBPROGRAMA sub, "
						+ "TCS_BEN_SUBP_ATR_BENEFICIARIO sab, paoyer.tcs_grupo_usuario gus, TCS_BEN_SUBPROGRAMA_USUARIO subus "
						+ "WHERE  gus.CODIGO = usu.GUS_CODIGO "
						+ "AND a.COD_PROGRAMA = pro.CODIGO "
						+ "AND pro.AREA_CODIGO = area.CODIGO "
						+ "AND pro.USU_CODIGO = usu.CODIGO "
						+ "AND pro.VIGENCIA = 'A' "
						+ "AND sub.prg_codigo = pro.codigo "
						+ "AND sab.SBPR_CODIGO = sub.codigo "
						+ "AND UPPER(TRIM(sab.nombre)) = 'GESTOR' ");

		if ((Object) codeUser != null) {
			query.append("AND ('ADMINISTRADOR GENERAL' = :userGroupName OR 'SUPER USUARIO' = :userGroupName "
					+ " OR admSubpro = :codeUser OR pro.USU_CODIGO = :codeUser "
					+ " OR a.permisos = :codeUser ");

			namedParameters.put("userGroupName", userGroupName);
			namedParameters.put("codeUser", codeUser);

			if (userGroupName != null
					&& userGroupName.equals("ADMINISTRADOR SECRETARIA")) {
				query.append(" OR COD_AREA = :COD_AREA ");
				namedParameters.put("COD_AREA", codeArea);
			}
			query.append(" ) ");
		} else {
			return null;
		}

		if (criterea.getCode() != null) {
			query.append("AND COD_PROGRAMA = :COD_PROGRAMA ");
			namedParameters.put("COD_PROGRAMA", criterea.getCode());
		}
		if (!criterea.getNombre().equalsIgnoreCase("")) {
			query.append("AND NOM_PROGRAMA LIKE :NOM_PROGRAMA ");
			namedParameters.put("NOM_PROGRAMA", "%"
					+ criterea.getNombre().toUpperCase().trim() + "%");
		}
		// TODO: check
		if (criterea.getCodeArea() != null) {
			query.append("AND COD_AREA = :COD_AREA ");
			namedParameters.put("COD_AREA", criterea.getCodeArea());
		}
		query.append(" ORDER BY NOM_PROGRAMA");

		List<ProgramaVO> programas = getNamedParameterJdbcTemplate().query(
				query.toString(), namedParameters, new RowMapper<ProgramaVO>() {

					public ProgramaVO mapRow(ResultSet rst, int arg1)
							throws SQLException {
						ProgramaVO pro = new ProgramaVO();
						pro.setCode(new Long(rst.getLong("COD_PROGRAMA")));
						pro.setNombre(rst.getString("NOM_PROGRAMA"));
						pro.setDescripcion(rst.getString("DESC_PROGRAMA"));
						pro.setObjetivo(rst.getString("OBJETIVO"));
						pro.setPoblacionObjetivo(rst
								.getString("POBLACION_OBJETIVO"));
						pro.setCodeArea(new Long(rst.getString("COD_AREA")));
						pro.setNombreArea(rst.getString("NOM_AREA"));
						pro.setCodeUsuario(new Long(rst
								.getString("COD_USUARIO")));
						pro.setNombreUsuario(rst.getString("NOM_USUARIO"));
						return pro;
					}
				});
		return programas;
	}

	public Collection<SubprogramaVO> findPermissionsReport(Long codeUser,
			String userGroupName, Long codePrograma, Long codeArea) {
		Map<String, Object> namedParametes = new HashMap<String, Object>();

		String query = "SELECT DISTINCT pro.CODIGO codprog,pro.NOMBRE nompro,subpro.codigo codeSubprograma, "
				+ " UPPER(subpro.nombre) nomSubprograma, usu.codigo,subpro.usu_codigo,pro.usu_codigo "
				+ " FROM TCS_BEN_SUBPROGRAMA subpro, "
				+ " TCS_BEN_PROGRAMA pro, "
				+ " TCS_BEN_SUBPROGRAMA_USUARIO subus, "
				+ " paoyer.tcs_usuario usu "
				+ " WHERE pro.codigo = subpro.PRG_CODIGO "
				+ " AND (subpro.CODIGO = subus.SBPR_CODIGO OR 'ADMINISTRADOR GENERAL' = :userGroupName "
				+ " OR 'SUPER USUARIO' = :userGroupName "
				+ " OR subpro.usu_codigo = :codeUser OR pro.usu_codigo = :codeUser) "
				+ " AND subus.USU_CODIGO = usu.CODIGO "
				+ " AND usu.CODIGO = :codeUser ORDER BY nompro";

		namedParametes.put("userGroupName", userGroupName);
		namedParametes.put("codeUser", codeUser);

		List<SubprogramaVO> subprogramas = getNamedParameterJdbcTemplate()
				.query(query, namedParametes, new RowMapper<SubprogramaVO>() {

					public SubprogramaVO mapRow(ResultSet rs, int rowNum)
							throws SQLException {
						SubprogramaVO vo = new SubprogramaVO();
						vo.setCode(new Long(rs.getLong("codeSubprograma")));
						vo.setNombre(rs.getString("nomSubprograma"));
						vo.setNombrePrograma(rs.getString("nompro"));
						return vo;
					}
				});
		return subprogramas;
	}

}
